Wicket Screencast 03 - Repeating Views

This screencast is part of a series about apache wicket. You can find the whole series and additional information on the Wicket Newsletter Screencast page. In this episode you’ll learn the basics about repeating views in Wicket:

  • RepeatingView: The simplest repeater component
  • ListView: For displaying Lists of Data
  • DataView: For displaying all kinds of data
  • Pagination

Transcript

Welcome to the third episode of my wicket screencast. Today’s topic is “repeating stuff”. We will display lists of data using ListView, RepeatingView and DataView. I will also show you how to use pagination. My name is david, you can find out all about me on my blog, davidtanzer.net, or you can follow me on Twitter, my name there is @dtanzer.

I have changed the application a little bit since the application a little bit since the last episode. For example, I have created a page class called “ListNewsletters” and added the imports we’ll need later, so you don’t have to watch me type import statements (which is rather boring). This HTML file (“ListNewsletters.html”) was already part of the project skeleton. It is a mockup of the newsletters list. But you can see, this mockup does not only contain the newsletters list. It also contains some text that should only show when there are no newsletters available, the so called “blank slate”.

This [blank slate] is here because an empty list does not look good. You should always display some blank slate instead of an empty list when there is no data to display. At the moment, both the blank slate and the actual content will show at the same time, but I want to change that now.

The blank slate should only show up when there are no newsletters, so we need the newsletter repository. For the repository, we need the size, which is the number of available newsletters. The blank slate and the content will be “WebMarkupContainer”s. WebMarkupContainer is a wicket component that does nothing. It is just a representation of some HTML in the page class.

I have already added the WebMarkupContainer for the blank slate, which only shows when the size is 0. And now I add another WebMarkupContainer for the content, which only shows when the size is not 0. Now I can compile and run the application, and after gradle has started the web server we should see that only the blank slate shows, and the list has disappeared.

The blank slate contains a link to the “create newsletter” form. This link in the mockup directly references CreateNewsletter.html, so it does not work yet, because it should not link directly to the static page but instead to the wicket page. For this we simply use “wicket:link” and add the correct path, and now wicket knows how to create the link so it references the “create newsletter” page.

When I restart the server I can click the link to create a new newsletter. After I have created the newsletter, the blank slate will disappear and the list of newsletters will show. This list of newsletters will, of course, still be empty, because we have not created any code to show the list yet.

Before I’ll populate the data I will start with a simpler example. I will create an unordered list which should contain the names of all newsletters. To create this I use the wicket component “RepeatingView”. A RepeatingView lets you add an arbitrary number of other components, so we add a new label for every newsletter we know. I got the list of newsletters from the repository, and to get this list I have to specify two parameters: The first newsletter we want to get and the number of newsletters. We just want to get the first 100 newsletters in this case. Don’t worry about the literal numbers, I will refactor this later anyway.

I iterate over all these newsletters with a foreach loop, and for every newsletter entity I add a label that shows the name of the newsletter. I don’t use a literal wicket:id here, I use “newChildId”, a method from RepeatingView to get an id that represents the next child of the repeating view. Not the page shows an unordered list with one entry. This entry shows the name of the newsletter we created earlier.

There is a better way to display lists of stuff in wicket: The ListView. ListView takes a java.util.List, iterates over it and calls a method for every item. I create an anonymous inner class of ListView and I have to override the method “populateItem”. The ListView will create a ListItem object for every item in the newsletter list and will call populateItem for every ListItem. In populateItem I get the newsletter entity from the list item and I add a label to the list item. The label contains the name of the newsletter. For this label I need an id. I use the id “name, there is no method “newChildId” anymore. The list allows us to specify how it will be rendered in the HTML file, so I add a span with the wicket:id “name” there.

When I reload the page, you won’t notice any difference at first, because we show almost the same HTML code. But when I inspect the page you can see that the “li” tag contains a “span” tag, so we really show the ListView now and not the RepeatingView anymore.

But there’s still a problem with this code: Actually we don’t want to show a list, we want to show the content of the repository! We only got the list because we received the first 100 items from the repository. What we really want to do is display some arbitrary data, and this arbitrary data is the whole content of our repository.

To do this, we create a DataView. The DataView does not display the content of a list, it gets its data to display from a DataProvider. I have to creat a class “NewsletterDataProvider”, and this class has to implement the interface “IDataProvider”. This interface defines four methods: “detach”, “size”, “iterator” and “model”.

We don’t need “detach” right now. The “size” method should return the number of items that can be displayed, and the “iterator” method should return an Iterator for a range of items. The range is specified by the index of the first item and the maximum number of items in the range. The last method we have to implement is “model”, which creates a “IModel” for a given object. Notice that I didn’t change the populateItem method from the ListView to the DataView. I just changed the type of the parameter from ListItem to Item, but everything else can stay the same.

Again, when I run the application now we should not see much of a change, because we render the same HTML as before. Now this list works pretty well, but we don’t want to show an unordered list, we want to show the table from our mockup. We can just change the design of our data view without changing any java code at all. We simply re-assign the wicket ids, and that’s it.

Now when we reload the application in the browser, we will see that the unordered list is gone, and that the table works. Now I add some more newsletters so you can see how a longer list looks like.

This list could become pretty long, so I want to add pagination here. To do this, we need another placeholder in the HTML with a wicket:id where we can show a PagingNavigator component. The PagingNavigator component is a wicket component that adds pagination to any other component that implements “IPageable” (the DataView does this). We want the data view to display only 5 items at a time. I specify this by adding another constructor parameter, and I add a PagingNavigator to the page. The PagingNavigator has to know the list, and that’s it, now we have paging functionality.

The pager does not look very pretty, but you can change this with some simple CSS rules.

Now you should know how to display repeating data using DataView, ListView and RepeatingView. In the next episode we will refactor the application. I will show you how to move some aspects out of the page classes to achieve a better separation of concerns. If you have any further questions, please contact me, my email address is business@davidtanzer.net, and my name is David.

You might also be interested in...